package org.dromara.system.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysFaultFeedback;
import org.dromara.system.domain.bo.SysFaultFeedbackAuditBo;
import org.dromara.system.domain.bo.SysFaultFeedbackBo;
import org.dromara.system.domain.bo.SysFaultFeedbackQueryBo;
import org.dromara.system.domain.vo.SysFaultFeedbackVo;
import org.dromara.system.mapper.SysFaultFeedbackMapper;
import org.dromara.system.service.ISysFaultFeedbackService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 故障反馈Service业务层处理
 *
 * @author system
 * @date 2025-10-10
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysFaultFeedbackServiceImpl implements ISysFaultFeedbackService {

    private final SysFaultFeedbackMapper baseMapper;

    /**
     * 反馈图片配置常量
     */
    private static final String FEEDBACK_FOLDER = "feedback/";
    private static final int MAX_IMAGES = 3;
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
    private static final String[] ALLOWED_TYPES = {"image/jpeg", "image/jpg", "image/png", "image/webp"};

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFaultFeedbackVo submitFeedback(SysFaultFeedbackBo bo, MultipartFile[] files) {
        // 1. 校验图片数量
        if (files != null && files.length > MAX_IMAGES) {
            throw new ServiceException("最多上传" + MAX_IMAGES + "张图片");
        }

        // 2. 上传图片到 MinIO（eviton/feedback/ 文件夹）
        List<String> imageUrls = new ArrayList<>();
        if (files != null && files.length > 0) {
            OssClient ossClient = OssFactory.instance();
            for (MultipartFile file : files) {
                // 校验文件大小
                if (file.getSize() > MAX_FILE_SIZE) {
                    throw new ServiceException("图片大小不能超过5MB");
                }

                // 校验文件类型
                String contentType = file.getContentType();
                if (!isImageType(contentType)) {
                    throw new ServiceException("只支持 jpg、png、webp 格式的图片");
                }

                try {
                    // 生成文件名：feedback/uuid.ext
                    String originalFilename = file.getOriginalFilename();
                    String extension = originalFilename != null && originalFilename.contains(".")
                        ? originalFilename.substring(originalFilename.lastIndexOf("."))
                        : ".jpg";
                    String fileName = FEEDBACK_FOLDER + IdUtil.fastSimpleUUID() + extension;

                    // 上传文件（使用 InputStream 方式）
                    UploadResult uploadResult = ossClient.upload(
                        file.getInputStream(), 
                        fileName, 
                        file.getSize(), 
                        contentType
                    );
                    imageUrls.add(uploadResult.getUrl());
                } catch (Exception e) {
                    log.error("图片上传失败", e);
                    throw new ServiceException("图片上传失败：" + e.getMessage());
                }
            }
        }

        // 3. 构建实体并保存
        SysFaultFeedback entity = MapstructUtils.convert(bo, SysFaultFeedback.class);
        entity.setImageUrls(imageUrls);
        entity.setStatus("PENDING"); // 初始状态：待审核

        baseMapper.insert(entity);

        // 4. 返回详情
        return queryById(entity.getFeedbackId());
    }

    @Override
    public TableDataInfo<SysFaultFeedbackVo> queryPageList(SysFaultFeedbackQueryBo queryBo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysFaultFeedback> lqw = buildQueryWrapper(queryBo);
        Page<SysFaultFeedbackVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        // 填充状态名称
        result.getRecords().forEach(this::fillStatusName);
        return TableDataInfo.build(result);
    }

    @Override
    public List<SysFaultFeedbackVo> queryList(SysFaultFeedbackQueryBo queryBo) {
        LambdaQueryWrapper<SysFaultFeedback> lqw = buildQueryWrapper(queryBo);
        List<SysFaultFeedbackVo> list = baseMapper.selectVoList(lqw);
        // 填充状态名称
        list.forEach(this::fillStatusName);
        return list;
    }

    @Override
    public SysFaultFeedbackVo queryById(Long feedbackId) {
        SysFaultFeedbackVo vo = baseMapper.selectVoById(feedbackId);
        if (vo != null) {
            fillStatusName(vo);
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean auditFeedback(SysFaultFeedbackAuditBo auditBo) {
        // 1. 查询反馈是否存在
        SysFaultFeedback entity = baseMapper.selectById(auditBo.getFeedbackId());
        if (entity == null) {
            throw new ServiceException("反馈记录不存在");
        }

        // 2. 校验状态（只能审核待审核的记录）
        if (!"PENDING".equals(entity.getStatus())) {
            throw new ServiceException("该反馈已审核，无法重复操作");
        }

        // 3. 更新审核信息
        entity.setStatus(auditBo.getStatus());
        entity.setAuditRemark(auditBo.getAuditRemark());
        entity.setAuditBy(LoginHelper.getUserId());
        entity.setAuditTime(new Date());

        return baseMapper.updateById(entity) > 0;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<SysFaultFeedback> buildQueryWrapper(SysFaultFeedbackQueryBo queryBo) {
        LambdaQueryWrapper<SysFaultFeedback> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(queryBo.getExcavatorModel()), SysFaultFeedback::getExcavatorModel, queryBo.getExcavatorModel());
        lqw.eq(StringUtils.isNotBlank(queryBo.getFaultPart()), SysFaultFeedback::getFaultPart, queryBo.getFaultPart());
        lqw.eq(StringUtils.isNotBlank(queryBo.getFaultSymptom()), SysFaultFeedback::getFaultSymptom, queryBo.getFaultSymptom());
        lqw.eq(StringUtils.isNotBlank(queryBo.getStatus()), SysFaultFeedback::getStatus, queryBo.getStatus());
        lqw.eq(queryBo.getCreateUserId() != null, SysFaultFeedback::getCreateBy, queryBo.getCreateUserId());
        lqw.between(queryBo.getBeginTime() != null && queryBo.getEndTime() != null,
            SysFaultFeedback::getCreateTime, queryBo.getBeginTime(), queryBo.getEndTime());
        lqw.orderByDesc(SysFaultFeedback::getCreateTime);
        return lqw;
    }

    /**
     * 校验文件类型
     */
    private boolean isImageType(String contentType) {
        if (contentType == null) {
            return false;
        }
        for (String allowedType : ALLOWED_TYPES) {
            if (contentType.toLowerCase().contains(allowedType.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 填充状态名称和默认值
     */
    private void fillStatusName(SysFaultFeedbackVo vo) {
        // 填充状态名称
        if (vo.getStatus() != null) {
            switch (vo.getStatus()) {
                case "PENDING":
                    vo.setStatusName("待审核");
                    break;
                case "APPROVED":
                    vo.setStatusName("已通过");
                    break;
                case "REJECTED":
                    vo.setStatusName("已驳回");
                    break;
                default:
                    vo.setStatusName(vo.getStatus());
            }
        }
        
        // 为 null 字段设置空字符串默认值（避免前端校验报错）
        if (vo.getRemark() == null) {
            vo.setRemark("");
        }
        if (vo.getAuditRemark() == null) {
            vo.setAuditRemark("");
        }
        if (vo.getAuditByName() == null) {
            vo.setAuditByName("");
        }
    }

}

